function out   = doMacroSpanRegressions_nonLinear(allYields,data,setupFilter,numPCAs)

[n1,n2] = size(allYields);
if n2 > n1
    allYields = allYields';
end
[n1,n2] = size(data);
if n2 > n1
    data = data';
end

% Macro variables
T      = size(data,1);
labor  = data(:,1);
wage   = data(:,2);
dc     = data(:,3);
infl   = data(:,4);
r      = data(:,5);
slope  = allYields(:,40)-allYields(:,4);    %long rate minus one-year rate

% Using all bond yields 
%[pcaLoadings, pcaFactors,~,~,pcaR2] = pca(allYields,'NumComponents',6);
% Using only the six bond yields in the estimation
[pcaLoadings, pcaFactors_x,~,~,pcaR2] = pca(data(:,5:10),'NumComponents',numPCAs);
pcaFactors = zeros(T,numPCAs+numPCAs*(numPCAs+1)/2);
pcaFactors(:,1:numPCAs) = pcaFactors_x;
idx = numPCAs;
for i=1:numPCAs
    for j=i:numPCAs
        idx = idx + 1;
        pcaFactors(:,idx) = pcaFactors_x(:,i).*pcaFactors_x(:,j);
    end
end

% Regression I
% M_t = beta0 + beta1'*pca_t + u_t
numBoot = 10000;
window  = 50;
tmp     = nwest(labor,[ones(T,1),pcaFactors],4);
if T < 1000
    [RBar2_se,RBar2_fractile] = getRBar2SEboot(labor,[ones(T,1),pcaFactors],window,numBoot);
    labor_regI = [tmp.rbar RBar2_fractile]*100;
else
    labor_regI = [tmp.rsqr tmp.rbar]*100;
end

tmp     = nwest(wage,[ones(T,1),pcaFactors],4);
if T < 1000
    [RBar2_se,RBar2_fractile] = getRBar2SEboot(wage,[ones(T,1),pcaFactors],window,numBoot);
    wage_regI = [tmp.rbar RBar2_fractile]*100;
else
    wage_regI = [tmp.rsqr tmp.rbar]*100;
end

tmp    = nwest(dc,[ones(T,1),pcaFactors],4);
if T < 1000
    [RBar2_se,RBar2_fractile] = getRBar2SEboot(dc,[ones(T,1),pcaFactors],window,numBoot);
    dc_regI    = [tmp.rbar RBar2_fractile]*100;
else
    dc_regI    = [tmp.rsqr tmp.rbar]*100;
end

tmp        = nwest(infl,[ones(T,1),pcaFactors],4);
if T < 1000
    [RBar2_se,RBar2_fractile] = getRBar2SEboot(infl,[ones(T,1),pcaFactors],window,numBoot);
    infl_regI  = [tmp.rbar RBar2_fractile]*100;
else
    infl_regI  = [tmp.rsqr  tmp.rbar]*100;
end

% r_t = beta0 + beta1'*M_t
tmp     = nwest(r(1:end,1),[ones(T,1),labor(1:end,1),infl(1:end,1),dc(1:end,1)],4); 
if T < 1000
    [R2_se,R2_fractile] = getR2SEboot(r(1:end,1),[ones(T,1),labor(1:end,1),infl(1:end,1),dc(1:end,1)],window,numBoot);
    r_regI_M  = [tmp.rsqr R2_fractile]*100;
else
    r_regI_M  = [tmp.rsqr*100 ];
end


% Regression II
% rx_t+m,k = beta0 + beta1'*pca_t + beta2'*M_t + u_t+m
%where  rx_t+m,k = -(k-m)/4*y_t+m,k-m + k/4*y_t_k - 1/4*y_t_m
m          = setupFilter.CSregress_m;
matSelect  = m:m:max(setupFilter.maturities);
shorRate   = allYields(1:T-m,m);
yieldsUsed = allYields(:,matSelect);
numYields  = size(yieldsUsed,2);
version    = 2;
if version == 1
    % as in Bauer and Rudebusch (2017)
    Y          = zeros(T-m,numYields-1);
    for i=1:numYields-1
        Y(:,i)  = (-m*i/4*yieldsUsed(1+m:T,i) + m*(i+1)/4*yieldsUsed(1:T-m,i+1) - m/4*shorRate);
    end
    X  = [ones(T-m,1),pcaFactors(1:end-m,:),labor(1:T-m,1),wage(1:T-m,1),dc(1:T-m,1),infl(1:T-m,1)];
    %X  = [ones(T-m,1),pcaFactors(1:end-m,:)];
    tmp = nwest(mean(Y,2),X,1);
    xhr_regII          = zeros(1,1+3);
    xhr_regII(1,1)     = tmp.rsqr;
    %xhr_regII(1,2:end) = tmp.beta';
    %tmp.tstat
else
    xhr_regII  = zeros(1,numYields-1);
    for i=1:numYields-1
        % Note that m*i gives k-m in relation to the notation above
        Y  = (-m*i/4*yieldsUsed(1+m:T,i) + m*(i+1)/4*yieldsUsed(1:T-m,i+1) - m/4*shorRate);
        X  = [ones(T-m,1),pcaFactors(1:end-m,:),labor(1:end-m,1),wage(1:end-m,1),dc(1:end-m,1),infl(1:end-m,1)];
        %X  = [ones(T-m,1),pcaFactors(1:end-m,:),dc(1:end-m,1),infl(1:end-m,1)];
        %X  = [ones(T-m,1),pcaFactors(1:end-m,:)];
        tmp = nwest(Y,X,2*4);
        xhr_regII(1,i)     = tmp.rsqr;
        
    end
end

% Regression III
% M_t+1 = beta0 + beta1'*pca_t + u_t+1
% tmp          = nwest(labor(2:end,1),[ones(T-1,1),pcaFactors(1:end-1,:)],0);
% labor_regIII = [tmp.rsqr*100];
% tmp          = nwest(wage(2:end,1),[ones(T-1,1),pcaFactors(1:end-1,:)],0);
% wage_regIII  = [tmp.rsqr*100];
% tmp          = nwest(dc(2:end,1),[ones(T-1,1),pcaFactors(1:end-1,:)],0);
% dc_regIII    = [tmp.rsqr*100 ];
% tmp          = nwest(infl(2:end,1),[ones(T-1,1),pcaFactors(1:end-1,:)],0);
% infl_regIII  = [tmp.rsqr*100];

% M_t+1 = beta0 + beta1'*pca_t + beta2'*M_t + u_t+1
tmp          = nwest(labor(2:end,1),[ones(T-1,1),pcaFactors(1:end-1,:),labor(1:end-1,1),dc(1:end-1,1),infl(1:end-1,1)],0);
labor_regIII = [tmp.rsqr tmp.beta(1:end,1)'];
tmp          = nwest(wage(2:end,1),[ones(T-1,1),pcaFactors(1:end-1,:),labor(1:end-1,1),dc(1:end-1,1),infl(1:end-1,1)],0);
wage_regIII  = [tmp.rsqr tmp.beta(1:end,1)'];
tmp          = nwest(dc(2:end,1),[ones(T-1,1),pcaFactors(1:end-1,:),labor(1:end-1,1),dc(1:end-1,1),infl(1:end-1,1)],0);
dc_regIII    = [tmp.rsqr tmp.beta(1:end,1)'];
tmp          = nwest(infl(2:end,1),[ones(T-1,1),pcaFactors(1:end-1,:),labor(1:end-1,1),dc(1:end-1,1),infl(1:end-1,1)],0);
infl_regIII  = [tmp.rsqr tmp.beta(1:end,1)'];

%% Correlation of slope with infl and r
tmp         = nwest(slope,[ones(T,1),infl],4);
slopeOnInfl = [tmp.rsqr tmp.beta(2,1) corr(slope,infl)];
tmp         = nwest(slope,[ones(T,1),r],4);
slopeOnR    = [tmp.rsqr tmp.beta(2,1) corr(slope,r)];

%% Ability of slope to forecast inflation and consumption
nn = 4;
tmp = nwest(dc(1+nn:T),[ones(T-nn,1)  slope(1:T-nn,1)],nn);
dcOnSlope = [tmp.rsqr tmp.beta(:,1)' tmp.tstat'];
tmp = nwest(infl(1+nn:T),[ones(T-nn,1)  slope(1:T-nn,1)],nn);
inflOnSlope = [tmp.rsqr tmp.beta(:,1)' tmp.tstat'];


%% Output
out.pcaR2        = pcaR2(:,1)';
out.labor_regI   = labor_regI;
out.wage_regI    = wage_regI;
out.dc_regI      = dc_regI;
out.infl_regI    = infl_regI;
out.r_regI_M     = r_regI_M;
out.xhr_regII    = xhr_regII;
out.labor_regIII = labor_regIII;
out.wage_regIII  = wage_regIII;
out.dc_regIII    = dc_regIII;
out.infl_regIII  = infl_regIII;
out.slopeOnInfl  = slopeOnInfl;
out.slopeOnR     = slopeOnR;
out.dcOnSlope     = dcOnSlope;
out.inflOnSlope  = inflOnSlope;
end